package uiMain;

import gestorbienraizok.inmuebles.Apartamento;
import gestorbienraizok.inmuebles.Casa;
import gestorbienraizok.inmuebles.Inmueble;
import gestorbienraizok.inmuebles.Torre;
import gestorbienraizok.inmuebles.Unidad;
import java.util.LinkedList;
import java.util.Scanner;
import static uiMain.bienRaizOk.entrada;
import static uiMain.bienRaizOk.listaDeUnidades;

public class OpcionBuscarPropiedadPorCriterios extends OpcionDeMenu {

    private String nombreParaMostrar = " Buscar una propiedad por criterios";

    @Override
    public void ejecutar() {
        boolean esApartamento = verificarCaracteristica("¿Desea buscar una casa o un apartamento? (C/A): ", "a", "c");

        boolean esParaArrendar = verificarCaracteristica("Seleccione el rol: compraventa (C) o arrendamiento (A): ", "a", "c");

        System.out.print("Ingrese el rango de área (en m2) separado por un guión (Ej. 50-120), ó '0' si es indiferente: ");
        entrada = new Scanner(System.in);
        String rangoArea = entrada.nextLine().trim();
        int areaMinima = 0;
        int areaMaxima = Integer.MAX_VALUE;

        if (!rangoArea.equals("0")) {
            areaMinima = Integer.parseInt(rangoArea.substring(0, rangoArea.indexOf("-")));
            areaMaxima = Integer.parseInt(rangoArea.substring(rangoArea.indexOf("-") + 1));
        }

        System.out.print("Ingrese el rango de estrato separado por un guión (Ej. 2-4), ó '0' si es indiferente: ");
        entrada = new Scanner(System.in);
        String rangoEstrato = entrada.nextLine().trim();
        byte estratoMinimo = 1;
        byte estratoMaximo = 6;

        if (!rangoEstrato.equals("0")) {
            estratoMinimo = Byte.parseByte(rangoEstrato.substring(0, rangoEstrato.indexOf("-")));
            estratoMaximo = Byte.parseByte(rangoEstrato.substring(rangoEstrato.indexOf("-") + 1));
        }

        System.out.print("¿La propiedad debe tener patio? (S/N) o 'X' si es indiferente: ");
        entrada = new Scanner(System.in);
        String debeTenerPatio = entrada.nextLine().toLowerCase();

        byte numeroDeBanhos = 0;
        do {
            System.out.print("¿Cuántos baños debe tener como mínimo la propiedad?: ");
            numeroDeBanhos = entrada.nextByte();
        } while (numeroDeBanhos < 0);

        byte numeroDeEspacios = 0;
        do {
            System.out.print("¿Cuántas piezas debe tener como mínimo la propiedad?: ");
            numeroDeEspacios = entrada.nextByte();
        } while (numeroDeEspacios < 0);

        String debeTenerParqueadero = "x";//Se inicializa asi para no generar error de compilacion
        byte numeroDeGarajes = 0;

        if (esApartamento) {
            System.out.print("¿El apartamento debe tener parqueadero? (S/N) o 'X' si es indiferente: ");
            entrada = new Scanner(System.in);
            debeTenerParqueadero = entrada.nextLine().toLowerCase();
        } else {
            do {
                System.out.print("¿Cuántos garajes debe tener como mínimo la casa?: ");
                numeroDeGarajes = entrada.nextByte();
            } while (numeroDeGarajes < 0);
        }

        String rangoValor;
        long valorMinimo = 0;
        long valorMaximo = Long.MAX_VALUE;

        if (esParaArrendar) {
            System.out.print("Ingrese el rango de tarifa mensual separado por un guión (Ej. 200000-600000), ó '0' si es indiferente: ");
            entrada = new Scanner(System.in);
            rangoValor = entrada.nextLine().toLowerCase();

            if (!(rangoValor.equals("0"))) {
                valorMinimo = Long.parseLong(rangoValor.substring(0, rangoValor.indexOf("-")));
                valorMaximo = Long.parseLong(rangoValor.substring(rangoValor.indexOf("-") + 1));
            }
        } else {
            System.out.print("Ingrese el rango del precio de venta separado por un guión (Ej. 200000-600000), ó '0' si es indiferente: ");
            entrada = new Scanner(System.in);
            rangoValor = entrada.nextLine().toLowerCase();

            if (!rangoValor.equals("0")) {
                valorMinimo = Long.parseLong(rangoValor.substring(0, rangoValor.indexOf("-")));
                valorMaximo = Long.parseLong(rangoValor.substring(rangoValor.indexOf("-") + 1));
            }
        }

        //Ya están recogidos todos los criterios
        LinkedList<Inmueble> listaDeInmueblesQueCumplen = new LinkedList();

        for (int i = 0; i < listaDeUnidades.size(); i++) {
            Unidad estaUnidad = listaDeUnidades.get(i);
            if (esApartamento) {
                if (estaUnidad.getNumeroDeApartamentos() != 0) {
                    for (int j = 0; j < estaUnidad.getListaDeTorres().size(); j++) {
                        Torre estaTorre = estaUnidad.getListaDeTorres().get(j);
                        for (int k = 0; k < estaTorre.getNumeroDeApartamentos(); k++) {
                            Apartamento esteApartamento = estaTorre.getListaDeApartamentos().get(k);
                            if (elApartamentoAplica(esteApartamento, esParaArrendar, areaMinima, areaMaxima,
                                    estratoMinimo, estratoMaximo, debeTenerPatio, numeroDeBanhos, numeroDeEspacios,
                                    debeTenerParqueadero, valorMinimo, valorMaximo)) {
                                listaDeInmueblesQueCumplen.add(esteApartamento);
                            }
                        }
                    }
                }

            } else { //Si es casa lo que se busca
                if (estaUnidad.getNumeroDeCasas() != 0) {
                    for (int j = 0; j < estaUnidad.getListaDeCasas().size(); j++) {
                        Casa estaCasa = estaUnidad.getListaDeCasas().get(j);
                        if (laCasaAplica(estaCasa, esParaArrendar, areaMinima, areaMaxima,
                                estratoMinimo, estratoMaximo, debeTenerPatio, numeroDeBanhos, numeroDeEspacios,
                                numeroDeGarajes, valorMinimo, valorMaximo)) {
                            listaDeInmueblesQueCumplen.add(estaCasa);
                        }
                    }
                }
            }
        }
        if (listaDeInmueblesQueCumplen.size() != 0) {

            if (esApartamento) {
                System.out.println("Los siguientes apartamentos cumplen con sus criterios de búsqueda:\n");
                System.out.println("Código   Dirección          Nombre de la unidad         Torre #   Valor");
                System.out.println("-------------------------------------------------------------------------------");
                for (int i = 0; i < listaDeInmueblesQueCumplen.size(); i++) {
                    Apartamento esteApartamento = (Apartamento) listaDeInmueblesQueCumplen.get(i);
                    System.out.println(esteApartamento.toStringParaBusquedaPorCriterios(esParaArrendar));
                }
            } else {
                System.out.println("Las siguientes casas cumplen con sus criterios de búsqueda:\n");
                System.out.println("Código   Dirección          Nombre de la unidad         Valor");
                System.out.println("---------------------------------------------------------------------");
                for (int i = 0; i < listaDeInmueblesQueCumplen.size(); i++) {
                    Casa estaCasa = (Casa) listaDeInmueblesQueCumplen.get(i);
                    System.out.println(estaCasa.toStringParaBusquedaPorCriterios(esParaArrendar));
                }
            }
        } else {
            System.out.println("Ningun" + ((esApartamento) ? " apartamento" : "a casa") + " cumple con sus criterios de búsqueda.");
        }

    }

    private boolean elApartamentoAplica(Apartamento esteApartamento, boolean seBuscaParaArrendar, int areaMinima,
            int areaMaxima, byte estratoMinimo, byte estratoMaximo, String debeTenerPatio, byte numeroDeBanhosMinimo,
            byte numeroDeEspaciosMinimo, String debeTenerParqueadero, long valorMinimo, long valorMaximo) {

        //Antes de comparar las caracteristicas, se verifica que el rol del apartamento no sea "No disponible"
        //y que tampoco haya sido ya vendido o arrendado.También que su rol coincida con el que se busca
        if (esteApartamento.getRol().equals("No disponible") || !esteApartamento.getDisponibilidad().equals("Disponible")) {
            return false;
        }

        boolean sePuedeArrendarElApto;
        if (esteApartamento.getRol().toLowerCase().contains("alquiler")) {
            sePuedeArrendarElApto = true;
        } else { //si solo esta para la venta
            sePuedeArrendarElApto = false;
        }

        boolean sePuedeVenderElApto;
        if (esteApartamento.getRol().toLowerCase().contains("venta")) {
            sePuedeVenderElApto = true;
        } else { //Si solo esta para arrendar
            sePuedeVenderElApto = false;
        }

        if (seBuscaParaArrendar && !sePuedeArrendarElApto) {
            return false;
        }

        if (!seBuscaParaArrendar && !sePuedeVenderElApto) {
            return false;
        }

        int areaApto = esteApartamento.getAreaTotal();
        byte estratoApto = esteApartamento.getEstrato();
        boolean patioApto = esteApartamento.tienePatio();
        byte numBanhosApto = esteApartamento.numeroDeBanhos();
        byte numEspaciosApto = esteApartamento.numeroDePiezas();
        boolean parqueaderoApto = esteApartamento.tieneParqueadero();
        long valorVentaApto = esteApartamento.getPrecioDeVenta();
        long valorArrendApto = esteApartamento.getTarifaDeArrendamiento();

        //Ya estan guardadas todas las caracteristicas del apartamento en variables. Ahora se puede comparar:
        if (areaApto < areaMinima || areaApto > areaMaxima) {
            return false;
        }

        if (estratoApto < estratoMinimo || estratoApto > estratoMaximo) {
            return false;
        }

        if (debeTenerPatio.equals("s")) {
            if (patioApto == false) {
                return false;
            }
        } else if (debeTenerPatio.equals("n")) {
            if (patioApto == true) {
                return false;
            }
        }

        if (numBanhosApto < numeroDeBanhosMinimo) {
            return false;
        }

        if (numEspaciosApto < numeroDeEspaciosMinimo) {
            return false;
        }

        if (debeTenerParqueadero.equals("s")) {
            if (parqueaderoApto == false) {
                return false;
            }
        } else if (debeTenerParqueadero.equals("n")) {
            if (parqueaderoApto == true) {
                return false;
            }
        }

        if (seBuscaParaArrendar) {
            if (valorArrendApto < valorMinimo || valorArrendApto > valorMaximo) {
                return false;
            }
        } else {
            if (valorVentaApto < valorMinimo || valorVentaApto > valorMaximo) {
                return false;
            }
        }

        return true;   //Si pasa todas las comprobaciones

    }

    private boolean laCasaAplica(Casa estaCasa, boolean seBuscaParaArrendar, int areaMinima, int areaMaxima,
            byte estratoMinimo, byte estratoMaximo, String debeTenerPatio, byte numeroDeBanhosMinimo,
            byte numeroDeEspaciosMinimo, byte numeroDeGarajesMinimo, long valorMinimo, long valorMaximo) {

        //Antes de comparar las caracteristicas, se verifica que el rol de la casa no sea "No disponible"
        //y que tampoco haya sido ya vendida o arrendada. También que su rol coincida con el que se busca
        if (estaCasa.getRol().equals("No disponible") || !estaCasa.getDisponibilidad().equals("Disponible")) {
            return false;
        }

        boolean sePuedeArrendarLaCasa;
        if (estaCasa.getRol().toLowerCase().contains("alquiler")) {
            sePuedeArrendarLaCasa = true;
        } else { //si solo esta para la venta
            sePuedeArrendarLaCasa = false;
        }

        boolean sePuedeVenderLaCasa;
        if (estaCasa.getRol().toLowerCase().contains("venta")) {
            sePuedeVenderLaCasa = true;
        } else { //Si solo esta para arrendar
            sePuedeVenderLaCasa = false;
        }

        if (seBuscaParaArrendar && !sePuedeArrendarLaCasa) {
            return false;
        }

        if (!seBuscaParaArrendar && !sePuedeVenderLaCasa) {
            return false;
        }

        int areaCasa = estaCasa.getAreaTotal();
        byte estratoCasa = estaCasa.getEstrato();
        boolean patioCasa = estaCasa.tienePatio();
        byte numBanhosCasa = estaCasa.numeroDeBanhos();
        byte numEspaciosCasa = estaCasa.numeroDePiezas();
        byte numGarajesCasa = estaCasa.getCantidadDeGarajes();
        long valorVentaCasa = estaCasa.getPrecioDeVenta();
        long valorArrendCasa = estaCasa.getTarifaDeArrendamiento();

        //Ya estan guardadas todas las caracteristicas de la casa en variables. Ahora se puede comparar:
        if (areaCasa < areaMinima || areaCasa > areaMaxima) {
            return false;
        }

        if (estratoCasa < estratoMinimo || estratoCasa > estratoMaximo) {
            return false;
        }

        if (debeTenerPatio.equals("s")) {
            if (patioCasa == false) {
                return false;
            }
        } else if (debeTenerPatio.equals("n")) {
            if (patioCasa == true) {
                return false;
            }
        }

        if (numBanhosCasa < numeroDeBanhosMinimo) {
            return false;
        }

        if (numEspaciosCasa < numeroDeEspaciosMinimo) {
            return false;
        }

        if (numGarajesCasa < numeroDeGarajesMinimo) {
            return false;
        }

        if (seBuscaParaArrendar) {
            if (valorArrendCasa < valorMinimo || valorArrendCasa > valorMaximo) {
                return false;
            }
        } else {
            if (valorVentaCasa < valorMinimo || valorVentaCasa > valorMaximo) {
                return false;
            }
        }

        return true;   //Si pasa todas las comprobaciones

    }

    @Override
    public String toString() {
        return nombreParaMostrar;
    }
    
    @Override
    public String toStringParaMostrarElNivel() {
        return nombreParaMostrar.trim().concat("...................................................................").substring(0,67) + "Funcionarios";
    }
}
